<?php

class Utils {
	/**
	* creates a string directory structure consisting of 8 total digits
	* and so a 2 will have a structure of 00/00/00/00000002
	* 
	* @param integer $id   the any int id
	* 
	* @return string   the directory formatted string
	*/
	public static function getDigitPath($id) {
		// while it is less than 8 digits
		while(strlen($id) < 8) {
			$id = "0".$id;
		}
		
		$path = substr($id, 0, 2)."/".substr($id, 2, 2)."/".substr($id, 4, 2)."/".$id;
		return $path;
	}

	/**
	 * Scales an image and transforms it into a jpeg. Requires libgd
	 * and installation of ezComponents Image base classes 
	 *
	 * @param string $source        the source file
	 * @param string $destination   the destination file
	 * @param integer $width        the desired final width
	 * @param integer $height       the desired final height
	 * 
	 * @return boolean true if successfully scaled, false if unsuccessful
	 */
	public static function scale_image($source, $destination, $width, $height) {
		
		$settings = new ezcImageConverterSettings(
	     array(
	         new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
	    	)
		);
	  
		$converter = new ezcImageConverter( $settings );
		$filters = array( 
		    new ezcImageFilter( 
		        'scale',
		        array( 
		            'width'     => $width,
		            'height'    => $height,
		            'direction' => ezcImageGeometryFilters::SCALE_DOWN,
		        )
		    ),
		);
	 	
		$converter->createTransformation( 'jpeg', $filters, array( 'image/jpeg' ) );
		try
		{
		    $converter->transform( 
		        'jpeg', 
		        $source, 
		        $destination 
		  );
		}
		catch( ezcImageTransformationException $e)
		{
			//die( "Error transforming the image: <{$e->getMessage()}>" );
			if(sfConfig::get('sf_logging_enabled')) {
				sfContext::getInstance()->getLogger()->info(
			  		"Error transforming the image: <{$e->getMessage()}>", 'err');			  		
			}
			return false;
		}
		return true;
	}
	
	public static function crop_thumbnail($source, $destination, $width, $height) {
		$image = new ezcImageAnalyzer($source);
		// echo "MIME type: {$image->mime} \n";
		// echo "Width: {$image->data->width} \n";
		// echo "Height: {$image->data->height} \n";
		// echo "Filesize:\t{$image->data->size} \n";

		$imageWidth = $image->data->width;
		$imageHeight = $image->data->height;

		$xStart = $imageWidth / 4;
		$yStart = $imageHeight / 8;
		if($imageWidth > $imageHeight) {	// if the picture is a landscape type
			$cropHeight = $imageHeight * .75;
			$cropWidth = $cropHeight;
		} else if($imageHeight > $imageWidth) {	// if the picture is a portrait type
			$cropWidth = $imageWidth * .75;
			$cropHeight = $cropWidth;
		} else {	// the width and height are equal
			$cropWidth = $imageWidth * .75;
			$cropHeight = $imageHeight * .75;
		}
		
		if(self::crop_image($source, $destination, $xStart, $yStart, $cropWidth, $cropHeight)) {
			return self::scale_image($destination, $destination, $width, $height);
		} else {
			return false;
		}		
	}

	public static function crop_image($source, $destination, $x, $y, $width, $height) {
		
		$settings = new ezcImageConverterSettings(
	     array(
	         new ezcImageHandlerSettings( 'GD', 'ezcImageGdHandler' ),
	    	)
		);
	  
		$converter = new ezcImageConverter( $settings );
		$filters = array( 
		    new ezcImageFilter( 
		        'crop',
		        array(
		        	'x'			=> (int)$x,
		        	'y'			=> (int)$y, 
		            'width'     => (int)$width,
		            'height'    => (int)$height,		            
		        )
		    ),
		);
	 	
		$converter->createTransformation( 'crop', $filters, array( 'image/jpeg' ) );
		try
		{
		    $converter->transform( 
		        'crop', 
		        $source, 
		        $destination 
		  );
		}
		catch( ezcImageTransformationException $e)
		{
			//die( "Error transforming the image: <{$e->getMessage()}>" );
			if(sfConfig::get('sf_logging_enabled')) {
				sfContext::getInstance()->getLogger()->info(
			  		"Error transforming the image: <{$e->getMessage()}>", 'err');			  		
			}
			return false;
		}
		return true;
	}	

	public static function extract_video_image($source, $destination, $frame=0) {
		if(isset($_ENV['OS']) && strpos(strtolower($_ENV['OS']), "windows") !== false) {
			$ffmpeg = '"'.realpath(sfConfig::get('sf_lib_dir').'\ffmpeg\windows\ffmpeg.exe').'"';
		} else {
			$ffmpeg = 'export LD_LIBRARY_PATH=/usr/local/lib; ';
			$ffmpeg .= 'ffmpeg';
		}
		
		$ffmpeg .= ' -itsoffset -%d -i "%s" -y -vcodec png -vframes 1 -an -f rawvideo -sameq "%s"';
		$cmd = sprintf($ffmpeg, $frame, $source, $destination);		
		$results = self::runExternal($cmd);
		return $results;
	}

	public static function transform_video($source, $destination) {
                if(isset($_ENV['OS']) && strpos(strtolower($_ENV['OS']), "windows") !== false) {
                        $mencoder = '"'.realpath(sfConfig::get('sf_lib_dir').'\mencoder\windows\mencoder.exe').'"';
                } else {
                        $mencoder = 'export LD_LIBRARY_PATH=/usr/local/lib; ';
                        $mencoder .= 'mencoder';
                }
		
		$mencoder .= ' -oac mp3lame -lameopts vol=10 -ovc lavc -o "%s" "%s"';
                $cmd = sprintf($mencoder, $destination, $source);
                $results = self::runExternal($cmd);
                return $results;
	}
	
	/**
	 * Convert a to a flash format
	 *
	 * @param String $source
	 * @param String $destination
	 */
	public static function convert_video($source, $destination) {
		if(isset($_ENV['OS']) && strpos(strtolower($_ENV['OS']), "windows") !== false) {
			$ffmpeg = '"'.realpath(sfConfig::get('sf_lib_dir').'\ffmpeg\windows\ffmpeg.exe').'"';
		} else {
			$ffmpeg = 'export LD_LIBRARY_PATH=/usr/local/lib; ';
			$ffmpeg .= 'ffmpeg';
		}
		
		$ffmpeg .= ' -i "%s" -ar 44100 "%s"';		
		$cmd = sprintf($ffmpeg, $source, $destination);
		$results = self::runExternal($cmd);
		return $results;
				
	}
	
	/**
	 * Executes an external OS command on the command line
	 * @return an array containing two elements:
	 *   {output} => result of the command execution
	 *   {return_code} => the return code of the command execution  
	 * @param $cmd, String of the command to execute
	 */
 	public static function runExternal($cmd) {
 		$code = null;
        $descriptorspec = array(
            0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
            1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
            2 => array("pipe", "w") // stderr is a file to write to
        );
       
        $pipes= array();
        $process = proc_open($cmd, $descriptorspec, $pipes, getcwd(), $_ENV, array('bypass_shell' => true) );
       
        $output= "";
       
        if (!is_resource($process)) return false;
        fwrite($pipes[0], '<?php print_r($_ENV); ?>');
        #close child's input imidiately
        fclose($pipes[0]);
       
        stream_set_blocking($pipes[1],false);
        stream_set_blocking($pipes[2],false);
       
        $todo= array($pipes[1],$pipes[2]);
       
        while( true ) {
            $read= array();
            if( !feof($pipes[1]) ) $read[]= $pipes[1];
            if( !feof($pipes[2]) ) $read[]= $pipes[2];
           
            if (!$read) break;
           
            $ready= stream_select($read, $write, $ex, 2);
           
            if ($ready === false) {
                break; #should never happen - something died
            }
           
            foreach ($read as $r) {
                $s= fread($r,1024);
                $output.= $s;
            }
        }
       
        fclose($pipes[1]);
        fclose($pipes[2]);
       
        $code= proc_close($process);
		
        $cmd_result = array('output' => $output, 'return_code' => $code);
        return $cmd_result;
    }

	/**
	 * Manufactures an instance of an FCK editor
	 * @param $name, the name to use for the input field within the form
	 * @return a single FCKEditor object
	 */
    public static function getFCKEditor($name = 'FCKEditor1') {
		include("web/fckeditor/fckeditor.php");

		$sBasePath = '/fckeditor/';
		$oFCKeditor = new FCKeditor($name) ;
		$oFCKeditor->BasePath = $sBasePath ;
		$oFCKeditor->Config['SkinPath'] = $sBasePath . 'editor/skins/Aluminum/' ;
		$oFCKeditor->Config['CustomConfigurationsPath'] = '/js/fckconfig.js';
		return $oFCKeditor;
    }
	
}
